
const commandLineUsage = require('command-line-usage')

const ws = require('ws')
const path = require('path')
const chalk = require('chalk')
const fs = require('fs')
const optionDefinitions = [
    {
        name: 'help',
        description: '帮助',
        alias: 'h',
        type: Boolean
      },
      { name: 'clientMode', alias: 'C', type: Boolean,description:  '客户端模式,可忽略'},
      { name: 'root', alias: 'r', type: String,description:"http服务器存放文件的目录,默认public" },
    { name: 'close', alias: 'c', type: Boolean,description:"是否发送完关闭" },
    { name: 'msg', alias: 'm', type: String,description:"发送原始信息" },
    { name: 'timeout', alias: 't', type: Number,description:"指定超时时间毫秒,保证可以收到websocket服务器信息默认",defaultOption:100},
    { name: 'pipeFile', alias: 'f', type: String,description:"文件通信的文件地址" },
    { name: 'wgt', alias: 'w', type: String,description:"发送wgt包地址,应用会自动拼接消息"},
    { name: 'host', alias: 'H', type: String,description:"websocket的主机地址包括端口ip:host"  },
    { name: 'sendMethod', alias: 'M', type: String,description:"连续发送数据的方式,file,time" },
    { name: 'url', alias: 'u', type: String,description:"websocket连接地址,例如wss://ip:host" },
  ]
  
const defaultWgtPath=`${process.cwd()}/public`
const pipeFile=`${process.cwd()}/pipe-ws.txt`
const usage = commandLineUsage([
  {
    header: 'Websocket 客户端',
    content: chalk.green(`连接websocket服务器发送信息,
如不使用-c标志,通过发送数据到${pipeFile},不断发送   
`)
  },
  {
    header: 'Options',
    optionList: optionDefinitions
  },
  {
    content: ''
  }
])


const commandLineArgs = require('command-line-args')

var  options={}
try {
     options = commandLineArgs(optionDefinitions) || {}
     const isShowHelp=options.help || (!options.host && !options.url) || (!options.wgt && !options.msg) || ((Object.keys(options).length==1 && options.clientMode))

     console.log("option",options)
     
     if(isShowHelp){
         console.log(usage)
         process.exit()
        
     }

} catch(e){
    console.log(e)
}




try {fs.mkdirSync(defaultWgtPath)} catch {}
const config={
  host:options['host'] || process.env.WS_CLIENT_HOST || '127.0.0.1:3000',
  wgt:options['wgt'] || process.env.WGT_PKG,
  public:options['public'] || defaultWgtPath,
  adminToken:'admin',
  'url':options.url,
}

let sendMethod=options.sendMethod?options.sendMethod:'time'

sendMethods={
    time:sendWithDateTime,
    file:sendWithFileContent
}
let msg=options.msg
mvWgtFile()
console.log('ccc',config.url)
let wsUrl=config.url?config.url:`ws://${config.host}/ws/uniapp/admin?token=${config.adminToken}`
var sock = new ws(wsUrl)

function reloadWgtMsg(wgt){
    return `{"cmd":"u","params":{"wgtUrl":"http://${config.host}/p/${path.basename(wgt)}"}}`
}

sock.on("open", function () {
    console.log("open",config)
    var msg=options.msg
    if(config.wgt){
        msg=(reloadWgtMsg(config.wgt))
    }
    if(msg){
        console.log(`msg ${msg}`)
        sock.send(msg)
        if(config.close){
            setTimeout(()=>{sock.close()},options.timeout)
        }
    }
   
});

sock.on("error", function(err) {
    console.log(`socket error: ${err},then exit`);
    process.exit(0)
});
sock.on("close", function() {
    console.log("socket ->close",arguments);
});

if(!options.close){
    console.log(`continue send msg ...${sendMethod}`)
    sendMethods[sendMethod].call(this,sock,pipeFile)
}
function sendWithDateTime(sock){
    setInterval(function() {
        sock.send(JSON.stringify({rand:Math.random().toString(32).substr(3),date:new Date().toLocaleString()}))
    },1000)
}
function sendWithFileContent(sock,pipeFile){
    fs.writeFileSync(pipeFile, "")
    var lastMsg=""
    setInterval(function() {
        var data=fs.readFileSync(pipeFile)
        var content=data.toString()
        if(content.trim()!=""){
            console.log("send msg",content)
            sock.send(content.trim())
            fs.truncateSync(pipeFile)
        }
    },200)
}

function mvWgtFile(){
    if(config.wgt && config.wgt.trim()!=""){
        if(path.extname(options.wgt)!='.wgt'){
            options.wgt=config.wgt.trim()+".wgt"
        }
        if(fs.existsSync(options.wgt)){
            let wgtPath=`${config.public}/${path.basename(options.wgt)}`
            //fs.unlinkSync(wgtPath)
            //会强制覆盖存在的文件
            console.log(wgtPath)
            fs.renameSync(options.wgt,wgtPath)
        }
    }
}